#pragma once

#include<iostream>
#include<fstream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cstdarg>
#include<unistd.h>
#include<sys/types.h>
#include<pthread.h>
#include"LockGuard.hpp"

bool gIsSave = false;
const std::string logname = "log.txt";
//1:日志处理方式
enum Level
{
    DEBUG = 0,
    INFO,
    WAITING,
    ERROR,
    FATAL
};
void SaveFile(const std::string &filename,const std::string &message)
{
    //C++追加方式打开文件
    std::ofstream out(filename,std::ios::app);
    if(!out.is_open())//检查文件是否成功打开
    {
        return;
    }
    out<<message;
    out.close();//关闭文件
}
std::string LevelTostring(int level)
{
    switch(level)
    {
        case DEBUG:
            return "DEBUG";
        case INFO:
            return "INFO";
        case WAITING:
            return "WAITING";
        case ERROR:
            return "ERROR";
        case FATAL:
            return "FATAL";
        default:
            return "Unknown";
    }
}
std::string GetimeString()
{
    time_t curr_time = time(nullptr);
    struct tm *format_time = localtime(&curr_time);
    if(format_time == nullptr)
    {
        return "none";
    } 
    char time_buffer[1024];
    snprintf(time_buffer,sizeof(time_buffer),"%d-%d-%d %d:%d:%d",
                        format_time->tm_year+1900,
                        format_time->tm_mon+1,
                        format_time->tm_mday,
                        format_time->tm_hour,
                        format_time->tm_min,
                        format_time->tm_sec);
    return time_buffer;
}
//全局锁
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
//日志等级，时间，代码行数文件名，内容
void LogMessage(std::string filename ,int line,bool issave,int level,const char *format, ...)
{
    std::string levelstr = LevelTostring(level);
    std::string timestr = GetimeString();
    pid_t selfid = getpid();

    char buffer[1024];
    va_list arg;
    va_start(arg,format);
    vsnprintf(buffer,sizeof(buffer),format,arg);
    va_end(arg);
    std::string message = "["+timestr+"]"
    +"["+levelstr+"]"+"["+std::to_string(selfid)+"]"
    +"["+filename+"]"+"["+std::to_string(line)+"]"+buffer+"\n";
    LockGuard lockguard(&lock);
    if(!issave)
    {
        std::cout<<message;
    }
    else
    {
        SaveFile(logname,message);
    }
}

#define LOG(level,format, ...)    \
do                                \
{                                 \
    LogMessage(__FILE__,__LINE__,gIsSave,level,format,##__VA_ARGS__);\
} while (0)
#define EnableFile()                \
do                                  \
{                                   \
    gIsSave = true;                 \
} while (0)                      
#define EnableScreen()  \
do                      \
{                       \
    gIsSave = false;                    \
} while (0)



